package cn.ilikes.tools.nosql.jpa.clients.indexs.index.lucenes.asytools;

import java.io.IOException;

import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.clients.indexs.ClientIndexingRunTimeException;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABIndexSource;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABLuceneIndexSource;

public class AsySharedLuceneService extends  IAsyLuceneService {

	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private AtomicInteger  i=new AtomicInteger(0);

	private ReadLock readlock = lock.readLock();

	private WriteLock writeLock = lock.writeLock();

	private static IAsyLuceneService syLuceneService;

	private ABLuceneIndexSource indexSource;

	private Analyzer analyzer;

	private Logger logger = Loggerfactory.instance(AsySharedLuceneService.class);

	private boolean init = false;

	private IndexWriter nowIndexWriter;

//	private IndexSearcher indexSearcher;
//
//	private IndexReader indexReader;

	private AsySharedLuceneService(ABIndexSource indexSource) {
		
		this.indexSource = (ABLuceneIndexSource) indexSource;
		init();

	}

	private static synchronized void create(ABIndexSource indexSource) {
		syLuceneService = new AsySharedLuceneService(indexSource);

	}

	public static IAsyLuceneService instance(ABIndexSource indexSource) {
		if (syLuceneService == null) {
			create(indexSource);
		}
		return syLuceneService;
	}

	@Override
	public void close() {
		
//			Loggerfactory.info(logger, "close   SharedLuceneService   indexReader  " + indexReader);
//		if (this.indexReader != null)
//			try {
//				indexReader.close();
//			} catch (IOException e) {
//
//				e.printStackTrace();
//			}
			
			Loggerfactory.info(logger, "close   SharedLuceneService  nowIndexWriter   " + nowIndexWriter);
			if (nowIndexWriter != null)
				try {
					nowIndexWriter.close();
				} catch (IOException e) {

					e.printStackTrace();
				}
				Loggerfactory.info(logger, "close   SharedLuceneService  Directory   " + nowIndexWriter.getDirectory());
				if (nowIndexWriter != null)
					try {
						nowIndexWriter.getDirectory().close();
					} catch (IOException e) {

						e.printStackTrace();
					}
	}

	@Override
	public IndexWriter createIndexWriter() {
		if (nowIndexWriter == null)
			synchronized (logger) {
				try {
					if (nowIndexWriter == null) {
						IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_41, this.analyzer);
						ABLuceneIndexSource luceneIndexSource = indexSource;
						Directory directory_ = luceneIndexSource.createDirectory();
						IndexWriter hdfsIndexWriter = new IndexWriter(directory_, indexWriterConfig);
						this.nowIndexWriter = hdfsIndexWriter;
					}
					return nowIndexWriter;
				} catch (IOException e) {
					Loggerfactory.error(logger, e.getMessage(), e);
					throw new ClientIndexingRunTimeException(e);
				}

			}
		return nowIndexWriter;
	}

	public IndexSearcher createIndexSearcher() {
		IndexSearcher searcher=null;
//		if (indexSearcher == null) 
		{
//			synchronized (logger) 
			{
				try {
					IndexReader reader = createIndexReader();
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create     index searcher " + reader);
					if (reader == null)return null;
					searcher = new IndexSearcher(reader);
//					this.indexSearcher = searcher;
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage(), e);
				}
			}
		}
		return searcher;
	}

	public IndexReader createIndexReader() {
		DirectoryReader  reader =null;
//		if (indexReader == null)
		{
			synchronized (logger) {
				try {
					ABLuceneIndexSource luceneIndexSource = indexSource;
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create  " + luceneIndexSource.getIndexConfigs().getName() + "  index reader  " + reader);
					IndexWriter indexWriter = createIndexWriter();
					reader =  DirectoryReader.open(indexWriter, true);
//					IndexReader reader = DirectoryReader.open(directory);
//					this.indexReader = reader;
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage());
				}
			}
		}
		return reader;
	}

	@Override
	public void init() {
		if (init)return;
		Loggerfactory.info(logger, "Start init Asy Sing Lucene  Service");
		init = true;
		createIndexWriter();
		createIndexReader();

	}

	@Override
	public void wirte(Document doc) {
		try {
			//writeLock.lock();
			System.out.println("================ wirte  i  "+i.get());
			if (Loggerfactory.isdebug(logger))Loggerfactory.debug(logger, "=== wirte == "+i);
			 i.set( i.get()+1);
			IndexWriter indexWriter = createIndexWriter();
			indexWriter.addDocument(doc);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//writeLock.unlock();
		}

	}

	@Override
	public void merg() {
		try {
			if (Loggerfactory.isdebug(logger))Loggerfactory.debug(logger, "=== merg == ");
			System.out.println("================ merg  i  "+i.get());
			//readlock.lock();
			nowIndexWriter.commit();
//			indexReader=null;
//			indexSearcher=null;
			i.set(0);
		            } catch (IOException e) {
			e.printStackTrace();
		}finally
		{
			//readlock.unlock();
			
		}
		
	}

}
